home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
objtools
/
tlbsp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
12KB
|
638 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* tlbsp -
* BSP sort a triangle list
*
* Paul Haeberli - 1991
*/
#include "stdio.h"
#include "gl.h"
#include "device.h"
#include "trilist.h"
#include "vect.h"
float fgetmousex();
float fgetmousey();
#define USEDOUBLES
#ifdef USEDOUBLES
#define FLOAT double
#define V3F(v) v3d((double *)v)
#define C3F(v) c3d((double *)v)
#define VECT dvect
#define VLERP dvlerp
#define VDOT dvdot
#define TRINORMAL dtrinormal
#else
#define FLOAT float
#define V3F v3f
#define C3F c3f
#define VECT vect
#define VLERP vlerp
#define VDOT vdot
#define TRINORMAL trinormal
#endif
#define TOLERANCE 0.000001
int dolines;
main(argc,argv)
int argc;
char **argv;
{
short val;
FLOAT x, y;
int rendermode;
if(argc<3) {
fprintf(stderr, "usage: tlbsp input.tl sort.tl\n");
exit(1);
}
foreground();
keepaspect(3,2);
winopen("tlbsp");
subpixel(1);
RGBmode();
gconfig();
cpack(0x00ffffff);
clear();
dolines = 0;
bspread(argv[1]);
bspsort();
bspdraw();
bsptofile(argv[2]);
exit(0);
#ifdef DEBUG
qdevice(LEFTMOUSE);
qdevice(MIDDLEMOUSE);
qdevice(WKEY);
while(1) {
switch(qread(&val)){
case REDRAW:
bspdraw();
break;
case LEFTMOUSE:
if(val) {
dolines = 1-dolines;
bspdraw();
}
break;
case MIDDLEMOUSE:
if(val) {
}
break;
case WKEY:
if(val) {
x = 2.0*(fgetmousex()-0.5);
y = 2.0*(fgetmousey()-0.5);
printf("cur pos %f %f\n",x,y);
}
break;
}
}
#endif
}
/*
* bsprender follows . . .
*
*/
#define TRITOL (0.000001)
typedef struct bsptri {
struct bsptri *left, *right;
VECT p[3], c[3], n;
FLOAT d;
} bsptri;
static bsptri *bsplist;
static int bspnpoly, bspnsliver, bspinter;
static int bspoutpolys, badsplit;
bsptri *sortbsplist();
bsptri *newtri()
{
bsptri *tri;
tri = (bsptri *)malloc(sizeof(bsptri));
tri->right = 0;
tri->left = 0;
return tri;
}
cpacktov(c,v)
long c;
VECT *v;
{
v->x = ((c>>0)&0xff)/255.0;
v->y = ((c>>8)&0xff)/255.0;
v->z = ((c>>16)&0xff)/255.0;
v->w = ((c>>24)&0xff)/255.0;
}
bspread(name)
char *name;
{
int i, ntri;
trilisttri tltri;
bsptri *tri;
VECT norm, p0, p1, p2;
ntri = tlopen(name);
bsplist = 0;
bspnpoly = 0;
bspnsliver = 0;
for(i=0; i<ntri; i++) {
tlread(&tltri);
p0.x = tltri.x0;
p0.y = tltri.y0;
p0.z = tltri.z0;
p1.x = tltri.x1;
p1.y = tltri.y1;
p1.z = tltri.z1;
p2.x = tltri.x2;
p2.y = tltri.y2;
p2.z = tltri.z2;
if(TRINORMAL(&p0,&p1,&p2,&norm,TRITOL)) {
tri = newtri();
tri->p[0] = p0;
cpacktov(tltri.c0,&tri->c[0]);
tri->p[1] = p1;
cpacktov(tltri.c1,&tri->c[1]);
tri->p[2] = p2;
cpacktov(tltri.c2,&tri->c[2]);
tri->n.x = norm.x;
tri->n.y = norm.y;
tri->n.z = norm.z;
tri->d = VDOT(&p0,&norm);
tri->left = bsplist;
bsplist = tri;
bspnpoly++;
} else {
bspnsliver++;
}
}
tlclose();
printf("bspread: npolys %d nsliver %d\n",bspnpoly,bspnsliver);
}
bspsort()
{
bspinter = 0;
badsplit = 0;
bsplist = sortbsplist(bsplist,bspnpoly,0);
printf("bspsort: n intersect %d\n",bspinter);
printf("bspsort: n bad split %d\n",badsplit);
}
bspdraw()
{
reshapeviewport();
ortho(-1.0,1.0,-1.0,1.0,-2.0,2.0);
cpack(0x00ffffff);
clear();
bspoutpolys = 0;
drawbsplist(bsplist);
printf("bspdraw: output polygons %d\n",bspoutpolys);
}
bsptofile(name)
char *name;
{
short magic;
FILE *outf;
outf = fopen(name,"w");
if(!outf) {
fprintf(stderr,"tlbsp: can't open output file\n");
exit(1);
}
magic = TLMAGIC;
fwrite(&magic,sizeof(short),1,outf);
writebsplist(outf,bsplist);
fclose(outf);
}
bspfree()
{
freebsplist(bsplist);
bsplist = 0;
}
#define E0 0x1
#define E1 0x2
#define E2 0x4
checksplit(list,split,intersect,nleft,nright)
bsptri *list, *split;
int *intersect, *nleft, *nright;
{
bsptri *try;
FLOAT d, dm, dp;
FLOAT pd[3];
*intersect = 0;
*nleft = 0;
*nright = 0;
d = split->d;
dm = d-TOLERANCE;
dp = d+TOLERANCE;
try = list;
while(try) {
if(try != split) {
pd[0] = VDOT(&split->n,&try->p[0]);
pd[1] = VDOT(&split->n,&try->p[1]);
pd[2] = VDOT(&split->n,&try->p[2]);
if(pd[0]<dp && pd[1]<dp && pd[2]<dp)
(*nleft)++;
else if(pd[0]>dm && pd[1]>dm && pd[2]>dm)
(*nright)++;
else
(*intersect)++;
}
try = try->left;
}
}
bsptri *sortbsplist(l,unsorted,level)
bsptri *l;
int unsorted, level;
{
int i, p;
bsptri *split, *try, *next;
bsptri *left, *right;
bsptri *newl, *bestsplit;
int leftun, rightun;
FLOAT d, dm, dp, param;
FLOAT pd[3];
int sign[3];
int intercode, vr, v0, v1, v2;
VECT ip0, ip1;
VECT ic0, ic1;
int checkn, checkl, checkr;
FLOAT mininter, frac;
if(level<6) {
for(i=0; i<level; i++)
fprintf(stderr," ");
fprintf(stderr,"at level %d: %d\n",level,unsorted);
}
if(!l)
return 0;
if(unsorted<=1)
return l;
/* figure out a sliting plane */
if(unsorted<25) {
split = l;
bestsplit = split;
mininter = unsorted;
while(split) {
checksplit(l,split,&checkn,&checkl,&checkr);
frac = checkl-checkr;
if(frac<0.0)
frac = -frac;
frac = checkn+(frac/unsorted);
if(mininter>frac) {
mininter = frac;
bestsplit = split;
}
split = split->left;
}
if(!split) {
/* printf("BEST %f\n",mininter); */
split = bestsplit;
}
} else {
p = rand()%unsorted;
split = l;
for(i=0; i<p; i++) {
split = split->left;
}
}
left = right = 0;
leftun = rightun = 0;
d = split->d;
dm = d-TOLERANCE;
dp = d+TOLERANCE;
try = l;
while(try) {
next = try->left;
if(try != split) {
pd[0] = VDOT(&split->n,&try->p[0]);
pd[1] = VDOT(&split->n,&try->p[1]);
pd[2] = VDOT(&split->n,&try->p[2]);
if(pd[0]<dp && pd[1]<dp && pd[2]<dp) {
try->left = left;
left = try;
leftun++;
} else if(pd[0]>dm && pd[1]>dm && pd[2]>dm) {
try->left = right;
right = try;
rightun++;
} else {
bspinter++;
intercode = 0;
if(pd[0]<d && pd[1]>d) {
intercode |= E0;
sign[0] = 1;
} else if(pd[0]>d && pd[1]<d) {
intercode |= E0;
sign[0] = 0;
}
if(pd[1]<d && pd[2]>d) {
intercode |= E1;
sign[1] = 1;
} else if(pd[1]>d && pd[2]<d) {
intercode |= E1;
sign[1] = 0;
}
if(pd[2]<d && pd[0]>d) {
intercode |= E2;
sign[2] = 1;
} else if(pd[2]>d && pd[0]<d) {
intercode |= E2;
sign[2] = 0;
}
vr = 0;
switch(intercode) {
case E2:
vr++;
case E1:
vr++;
case E0:
v0 = (0+vr)%3;
v1 = (1+vr)%3;
v2 = (2+vr)%3;
param = (d-pd[v0])/(pd[v1]-pd[v0]);
VLERP(&try->p[v0],&try->p[v1],&ip0,param);
VLERP(&try->c[v0],&try->c[v1],&ic0,param);
newl = newtri(); /* neg side */
newl->p[v0] = try->p[v0];
newl->c[v0] = try->c[v0];
newl->p[v1] = ip0;
newl->c[v1] = ic0;
newl->p[v2] = try->p[v2];
newl->c[v2] = try->c[v2];
newl->n = try->n;
newl->d = try->d;
if(sign[v0]) {
newl->left = left;
left = newl;
leftun++;
} else {
newl->left = right;
right = newl;
rightun++;
}
newl = newtri(); /* pos side */
newl->p[v0] = ip0;
newl->c[v0] = ic0;
newl->p[v1] = try->p[v1];
newl->c[v1] = try->c[v1];
newl->p[v2] = try->p[v2];
newl->c[v2] = try->c[v2];
newl->n = try->n;
newl->d = try->d;
if(sign[v0]) {
newl->left = right;
right = newl;
rightun++;
} else {
newl->left = left;
left = newl;
leftun++;
}
free(try);
break;
case E2|E0:
vr++;
case E1|E2:
vr++;
case E0|E1:
v0 = (0+vr)%3;
v1 = (1+vr)%3;
v2 = (2+vr)%3;
param = (d-pd[v0])/(pd[v1]-pd[v0]);
VLERP(&try->p[v0],&try->p[v1],&ip0,param);
VLERP(&try->c[v0],&try->c[v1],&ic0,param);
param = (d-pd[v2])/(pd[v1]-pd[v2]);
VLERP(&try->p[v2],&try->p[v1],&ip1,param);
VLERP(&try->c[v2],&try->c[v1],&ic1,param);
newl = newtri(); /* neg side */
newl->p[v0] = try->p[v0];
newl->c[v0] = try->c[v0];
newl->p[v1] = ip0;
newl->c[v1] = ic0;
newl->p[v2] = try->p[v2];
newl->c[v2] = try->c[v2];
newl->n = try->n;
newl->d = try->d;
if(sign[v0]) {
newl->left = left;
left = newl;
leftun++;
} else {
newl->left = right;
right = newl;
rightun++;
}
newl = newtri(); /* neg side */
newl->p[v0] = ip0;
newl->c[v0] = ic0;
newl->p[v1] = ip1;
newl->c[v1] = ic1;
newl->p[v2] = try->p[v2];
newl->c[v2] = try->c[v2];
newl->n = try->n;
newl->d = try->d;
if(sign[v0]) {
newl->left = left;
left = newl;
leftun++;
} else {
newl->left = right;
right = newl;
rightun++;
}
newl = newtri(); /* pos side */
newl->p[v0] = ip0;
newl->c[v0] = ic0;
newl->p[v1] = try->p[v1];
newl->c[v1] = try->c[v1];
newl->p[v2] = ip1;
newl->c[v2] = ic1;
newl->n = try->n;
newl->d = try->d;
if(sign[v0]) {
newl->left = right;
right = newl;
rightun++;
} else {
newl->left = left;
left = newl;
leftun++;
}
free(try);
break;
default:
printf("strange code %d\n",intercode);
badsplit++;
}
}
}
try = next;
}
split->left = sortbsplist(left,leftun,level+1);
split->right = sortbsplist(right,rightun,level+1);
return split;
}
freebsplist(l)
bsptri *l;
{
if(l->left)
freebsplist(l->left);
if(l->right)
freebsplist(l->right);
if(l)
free(l);
}
drawbsplist(l)
bsptri *l;
{
bsptri *a, *b;
if(!l)
return;
if(l->n.z > 0.0) {
a = l->left;
b = l->right;
} else {
b = l->left;
a = l->right;
}
if(a)
drawbsplist(a);
bspoutpolys++;
if(dolines) {
cpack(0x00ffffff);
bgnpolygon();
V3F(&l->p[0]);
V3F(&l->p[1]);
V3F(&l->p[2]);
endpolygon();
cpack(0x00000000);
bgnclosedline();
V3F(&l->p[0]);
V3F(&l->p[1]);
V3F(&l->p[2]);
endclosedline();
} else {
bgnpolygon();
C3F(&l->c[0]);
V3F(&l->p[0]);
C3F(&l->c[1]);
V3F(&l->p[1]);
C3F(&l->c[2]);
V3F(&l->p[2]);
endpolygon();
}
if(b)
drawbsplist(b);
}
unsigned long vecttocpack( v )
VECT *v;
{
int r, g, b, a;
unsigned long c;
r = 255.0*v->x;
g = 255.0*v->y;
b = 255.0*v->z;
a = 255.0*v->w;
c = (a<<24) + (b<<16) + (g<<8) + (r<<0);
return c;
}
writebsplist(outf,l)
FILE *outf;
bsptri *l;
{
bsptri *a, *b;
trilisttri tltri;
if(!l)
return;
if(l->n.z > 0.0) {
a = l->left;
b = l->right;
} else {
b = l->left;
a = l->right;
}
if(a)
writebsplist(outf,a);
tltri.x0 = l->p[0].x;
tltri.y0 = l->p[0].y;
tltri.z0 = l->p[0].z;
tltri.c0 = vecttocpack(l->c+0);
tltri.x1 = l->p[1].x;
tltri.y1 = l->p[1].y;
tltri.z1 = l->p[1].z;
tltri.c1 = vecttocpack(l->c+1);
tltri.x2 = l->p[2].x;
tltri.y2 = l->p[2].y;
tltri.z2 = l->p[2].z;
tltri.c2 = vecttocpack(l->c+2);
fwrite(&tltri,sizeof(trilisttri),1,outf);
if(b)
writebsplist(outf,b);
}
c3d(d)
double d[3];
{
float f[3];
f[0] = d[0];
f[1] = d[1];
f[2] = d[2];
c3f(f);
}